<template>
  <table
    border="1"
    class="my-table"
  >
    <thead>
      <tr>
        <th
          v-for="info of tHead"
          :key="info.key"
        >{{info.text}}</th>
      </tr>
    </thead>
    <tbody>
      <tr
        v-for="(item,index) of tBody"
        :key="item"
      >
        <td
          v-for="(value,key) in item"
          :key="key"
          @click.stop="showEidtInput($event,key,index)"
        >
          {{value}}
        </td>
      </tr>
    </tbody>
  </table>
</template>
<script setup>
import { reactive, toRefs, createApp } from "vue";
import EditInput from "./EditInput";

let EditInputApp = null; //input编辑框

const state = reactive({
  key: "",
  value: "",
  index: -1
});

const props = defineProps({
  data: {
    type: Object,
    default: () => ({
      tHead: [],
      tBody: []
    })
  }
});

const emit = defineEmits(['submit']);

const { tHead, tBody } = toRefs(props.data);
//点击显示编辑输入框
const showEidtInput = (event, key, index) => {
  console.log("event", event.target.textContent);
  if (!checkEditable(key)) return;

  //每次点击可编辑的td，先将input编辑框初始化(卸载，初始化里面的数据)
  EditInputApp && removeEditInput(EditInputApp);

  const target = event.target;
  const oFrag = document.createDocumentFragment(); //创建虚拟的节点对象

  //创建input编辑框
  EditInputApp = createApp(EditInput, {
    value: event.target.textContent,
    setValue
  });

  //判断EditInputApp是否存在
  if (EditInputApp) {
    EditInputApp.mount(oFrag); //将EditInputApp挂载到虚拟节点中。
    target.appendChild(oFrag);
    target.querySelector(".edit-input").select(); //用于选择.edit-input的文本
  }

  //将点击的td的数据传进input编辑框里，用于回显数据
  setReactiveData({ key, index });
};

//检查是否为可编辑的项
const checkEditable = key => {
  //找出tBody中与tHead中对应key的那一项的editable（true、false）
  const { editable } = tHead.value.find(item => item.key === key);
  return editable;
};

//设置input编辑框的value值
const setValue = value => {
  state.value = value;
  emit("submit", { ...state });
};

//回显input编辑框的值
const setReactiveData = ({ index, key, value = "" }) => {
  state.index = index;
  state.key = key;
  state.value = value;
};

//卸载组件-移除input编辑框
const removeEditInput = app => {
  app && app.unmount(); //卸载一个已挂载的应用实例。
  setReactiveData({
    key: "",
    value: "",
    index: -1
  });

  //点击任意地方关闭input编辑框，在td中用了@click.stop，阻止冒泡，不会调用这个方法
  window.addEventListener("click", () => removeEditInput(EditInputApp), false);
};
</script>

<style scoped lang="scss">
.my-table {
  width: 100%;
  border-collapse: collapse;

  tr {
    height: 44px;
  }

  td {
    position: relative;
    text-align: center;
    cursor: pointer;
  }
}
</style>